package org.tp;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/* stack of scopes implementing the environnement */

/** Classe permettant de creer les environnements**/
public class Env {
	protected static int nb=0;	
	protected static int scopenb=0;

	/* double linked list */
	private Env prev;
	private Env next;
	private ScopeTree root; /* scope on top of the stack */
	private int num;   // used in toDot
	private int scopenum;

	/*
    public Env(Env prev, Env next, ArbreSym root) {
	this.prev=prev;
	this.next=next;
	this.root=root;
	this.num=nb++;
	this.scopenum=scopenb++;
    }
	 */ 
	public Env(Env prev, Env next) {
		 this.prev=prev;
         this.next=next;
         this.root=null;
         this.num=nb++;
         //System.out.println("num =" + this.num);
         scopenb = scopenb+1;
         scopenum=scopenb;
         //this(prev, next, null);
	}

	public Env(Env prev){
		this(prev,null);
	}
	public Env() {
		this(null,null);
	}
	/** Accesseur pour le numero d'environnement**/
	public int getNum() {
		return num;
	}

	public int getScopeNum() {
		return scopenum;
	}
	/** Accesseur permettant de revenir a l'environnement precedent**/
	public Env getPrev() {
		return prev;
	}
	/**  Acceseur pour remplacer l'environnement courant par son prochain**/
	public void putPrev(Env prev) {
		this.prev = prev;
	}
	/** Accesseur pour recuperer l'environnement suivant**/
	public Env getNext() {
		return next;
	}
	/** Accesseur pour modifier l'environnement suivant**/
	public void putNext(Env next) {
		this.next = next;
	}
	/** Accesseur pour recuperer la racine de l'arbre d'environnement**/
	public ScopeTree getRoot() {
		return root;
	}
	/** Ecriture des environnements dans un fichier **/
	public void toDot(String file) {
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter("./"+file+".dot"));
			StringBuffer str = new StringBuffer();
			str.append("digraph Env {");
			/***
    str.append("subgraph {node [shape=\"box\"]; rank=same;");
			 ***/
			for (Env e=this; e!=null; e=e.next){
				//System.out.println("dans todot de env scopenum vaut : " + e.scopenum);
				str.append(e.scopenum+" [shape=\"box\", label=\"s"+e.scopenum+"\"];"+"\n");
				//if (e.next!=null)
				//  str.append(e.id+" -> "+e.next.id+";\n");
			}
			/**
   str.append("};");
			 **/
			for (Env e=this; e!=null; e=e.next){
				if (e.root !=null){
					e.root.toDot(str);
					str.append(e.scopenum+" -> "+e.root.getNum()+";\n");
				}
			}
			str.append("}");
			out.write(str.toString());
			out.close();

		} catch (IOException e) {
			System.out.println("ERROR: build dot");
		}               
	}

	/** Ajouter une declaration dans l'arbre d'environnement**/
	public void add(String s, Type t) {
		if (root==null){
			System.out.println("PLIP");
			if (prev!=null && prev.root!=null){
				System.out.println("PLAP");
				root=new ScopeTree(prev.root.getLeft(), prev.root.getRight(), prev.root.getTag(), prev.root.getType()); 
				root=root.add(s, t, root);
				System.out.println("PLAP2");
			} else {
				System.out.println("PLUP");
				root=new ScopeTree(s, t);
				root=root.add(s, t, root);
				System.out.println("PLUP2");
			}
		} else {	
			System.out.println("PLYP");
			root=root.add(s, t, root);
			System.out.println("PLYP2");
		}
	}
	/** Ajouter une declaration dans l'arbre d'environnement**/
	public void add(String s)
	{
		add(s,null);
	}
	/** chercher une declaration dans l'arbre d'environnement**/
	public Type find(String s){
		if (root!=null)
			return root.find(s);
		else
			return null;
	}

}
